package com.hexun.busi.share.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.hexun.busi.client.RelationApiClient;
import com.hexun.busi.client.StockApiClient;
import com.hexun.busi.common.ThreadPoolUtils;
import com.hexun.busi.common.constants.Constants;
import com.hexun.busi.common.mybatis.BaseMybatisDao;
import com.hexun.busi.common.page.Page;
import com.hexun.busi.common.redis.RedisUtilService;
import com.hexun.busi.common.request.BaseResponse;
import com.hexun.busi.common.user.UserInfoVO;
import com.hexun.busi.common.utils.AESEncryptUtils;
import com.hexun.busi.common.utils.DateUtils;
import com.hexun.busi.common.utils.Encrypt;
import com.hexun.busi.common.utils.ParameterUtils;
import com.hexun.busi.common.utils.RespErrorUtils;
import com.hexun.busi.common.utils.StringUtils;
import com.hexun.busi.common.utils.http.HttpUtils;
import com.hexun.busi.share.common.config.Config;
import com.hexun.busi.share.common.config.ShareConstants;
import com.hexun.busi.share.entity.BusiUser;
import com.hexun.busi.share.mapper.BusiUserMapper;
import com.hexun.busi.share.service.UserService;

@Service
public class UserServiceImpl extends BaseMybatisDao<BusiUser> implements UserService {

	private Logger log = LoggerFactory.getLogger(getClass());

	@Resource
	private RedisUtilService redisUtilService;
	@Resource
	private Config config;
	@Resource
	private BusiUserMapper busiUserMapper;
	@Resource
	private StockApiClient stockApiClient;
	@Resource
	private RelationApiClient relationApiClient;

	@Override
	public BaseResponse modifyNickName(HttpServletRequest request) {
		BaseResponse resp = new BaseResponse();
		Map<String, String> dataMap = ParameterUtils.convertMap(request.getParameterMap(), Constants.charset_utf_8);
		dataMap.put("user_id",String.valueOf(request.getSession().getAttribute("user_id")));
		log.info("** 修改昵称接口接收到的{}请求信息:{}", request.getMethod(), JSON.toJSON(dataMap));
		// 1、参数验证
		String userId = dataMap.get("user_id");
		if (StringUtils.isBlank(userId)) {
			return RespErrorUtils.errorMgs(resp, "获取用户信息失败");
		}
		String nickname = dataMap.get("nick_name");
		if (StringUtils.isBlank(nickname)) {
			return RespErrorUtils.errorMgs(resp, "新的昵称不可为空");
		}
		Map<String, String> map = new HashMap<>();
		map.put("nickname", nickname);
		map.put("id", userId);
		map.put("from", config.getModifyNickNameIdentification());
		String code = Encrypt.getMD5(map.get("id") + "nickName" + map.get("from"));
		map.put("code", code);
		String result = HttpUtils.sendPost(config.getModifyNickNameUrl(), map);
		log.info(" ** 用户修改昵称返回值：{}", result);
		if (StringUtils.isBlank(result)) {
			return RespErrorUtils.errorMgs(resp, "网络异常，稍后重试！");
		}else if (!JSON.parseObject(result).getString("code").equals("1")){
			return RespErrorUtils.errorMgs(resp, JSON.parseObject(result).getString("msg"));
		}

		// 20180512 zhoudong add start 修改成功后，同步修改缓存内容
		fillUserInfo(dataMap);
		// 20180512 zhoudong add end

		return BaseResponse.getSuccess(resp, JSON.parseObject(result));
	}

	/**
	 * 加载用户信息
	 * @auther: zhoudong
	 * @date: 2018/5/9 14:47
	 */
	@Override
	public UserInfoVO loadUserInfo(String userId) {
		Map<String,String> map = null;
		// 1、从缓存取数据
		String result = redisUtilService.get(ShareConstants.USER_INFO_KEY + userId);
		UserInfoVO userInfoVO = null;
		if(StringUtils.isBlank(result)){

			// 2、从数据库查询数据
			BusiUser dbUser = busiUserMapper.selectByPrimaryKey(userId);
			// 3、从大网取数据
			if(dbUser == null){
				map = new HashMap<>();
				map.put("client",config.getUserInfoClient());
				map.put("id",userId);
				map.put("fromhost","wx-share");
				String code = Encrypt.getMD5(map.get("client") + DateUtils.getReqDateyyyyMMdd(new Date()) + config.getUserInfoKey() + userId);
				map.put("code", code);

				result = HttpUtils.sendPost(config.getUserInfoUrl(),map);

				if(StringUtils.isNotBlank(result)){
					userInfoVO = JSON.toJavaObject(JSON.parseObject(result),UserInfoVO.class);
					userInfoVO.setPhoto(userInfoVO.getPhoto().replace("-40","-150"));
					redisUtilService.set(ShareConstants.USER_INFO_KEY + userId,JSON.toJSONString(userInfoVO));
					// 准备入库，新开一个线程，忽略存储结果
					UserInfoVO finalUserInfoVO = userInfoVO;
					ThreadPoolUtils.fixedThreadPool.execute( () -> insert(finalUserInfoVO));
				}
			}else{
				userInfoVO = new UserInfoVO();
				BeanUtils.copyProperties(dbUser,userInfoVO);
				redisUtilService.set(ShareConstants.USER_INFO_KEY + userId,JSON.toJSONString(userInfoVO));
			}
		}else{
			userInfoVO = JSON.toJavaObject(JSON.parseObject(result), UserInfoVO.class);
		}
		return userInfoVO;
	}

	/**
	 * 用户信息入库
	 * @auther: zhoudong
	 * @date: 2018/5/30 10:36
	 * @param userInfoVO
	 */
	private synchronized int insert(UserInfoVO userInfoVO){
		// 1、转实体
		BusiUser busiUser = new BusiUser();
		BeanUtils.copyProperties(userInfoVO,busiUser);
		if(busiUser == null || StringUtils.isBlank(busiUser.getUserid())) return 0;
		busiUser.setCreateTime(new Date());

		// 2、从数据库查询数据
		BusiUser dbUser = busiUserMapper.selectByPrimaryKey(busiUser.getUserid());
		int flag = 0;
		// 3、数据库是否存在记录，存在update、不存在insert
		if(dbUser == null){
			if(StringUtils.isBlank(busiUser.getGrade())) busiUser.setGrade(-2);
			flag = busiUserMapper.insert(busiUser);
		}else flag = busiUserMapper.updateByPrimaryKeySelective(busiUser);
		return flag;
	}


	/**
	 * 补充用户信息
	 * @auther: zhoudong
	 * @date: 2018/5/12 11:03
	 */
	@Override
	public BaseResponse fillUserInfo(Map<String, String> dataMap) {
		BaseResponse resp = new BaseResponse();

		ParameterUtils.decodeValue(dataMap);

		String nickname = dataMap.get("nick_name");
		String photo = dataMap.get("photo");
		String userId = dataMap.get("user_id");
		String gender = dataMap.get("gender");
		String city = dataMap.get("city");
		String province = dataMap.get("province");
		String country = dataMap.get("country");
		String grade = dataMap.get("grade");

		if(StringUtils.isBlank(userId)){
			return RespErrorUtils.errorMgs(resp,"获取用户信息失败");
		}

		UserInfoVO userInfoVO = loadUserInfo(userId);
		if(userInfoVO == null){
			return RespErrorUtils.errorMgs(resp,"未查询到对应用户");
		}
		log.info(" ** 查询到用户信息：{}",JSON.toJSONString(userInfoVO));
		if(StringUtils.isNotBlank(nickname)) userInfoVO.setNickname(nickname);
		if(StringUtils.isNotBlank(photo)) userInfoVO.setPhoto(photo);

		if(StringUtils.isNotBlank(gender)) userInfoVO.setGender(gender);
		if(StringUtils.isNotBlank(city)) userInfoVO.setCity(city);
		if(StringUtils.isNotBlank(province)) userInfoVO.setProvince(province);
		if(StringUtils.isNotBlank(country)) userInfoVO.setCity(country);
		if(StringUtils.isNotBlank(grade)) userInfoVO.setGrade(Integer.parseInt(grade));

		String userVOStr = JSON.toJSONString(userInfoVO);
		redisUtilService.set(ShareConstants.USER_INFO_KEY + userId,userVOStr);

		// 准备入库，新开一个线程，忽略存储结果
		ThreadPoolUtils.fixedThreadPool.execute( () -> insert(userInfoVO));

		return BaseResponse.getSuccess(resp,"补充用户信息成功");
	}
	
	/**
	 * 获取和讯openid
	 * @auther: zhoudong
	 * @date: 2018/5/23 9:26
	 */
	@Override
	public String loadOpenId(String userId) {
		String openId = AESEncryptUtils.encrypt(userId,config.getOpenIdKey());
		if(StringUtils.isNotBlank(openId)){
			openId = AESEncryptUtils.base64Encode(openId);
		}
		log.info(" userId:{},openId:{}",userId,openId);
		return openId;
	}

	/**
	 * 根据openid 解密userId
	 * @auther: zhoudong
	 * @date: 2018/5/23 9:26
	 */
	@Override
	public String decryptUserId(String openId) {
		String userId = AESEncryptUtils.base64decrypt(openId);
		if(StringUtils.isNotBlank(openId)){
			userId = AESEncryptUtils.decrypt(userId,config.getOpenIdKey());
		}
		log.info(" userId:{},openId:{}",userId,openId);
		return userId;
	}
	/**
	 * 根据用户昵称搜索
	 * @auther: zhoudong
	 * @date: 2018/5/30 11:05
	 */
	@Override
	public Page<UserInfoVO> loadUserByNickname(String nickName, String userId, Page<UserInfoVO> page) {
		// 1、参数
		Map<String,Object> map = new HashMap<>();
		map.put("nickname",nickName);
		map.put("userid",userId);
		// 2、查库
		Page<BusiUser> busiPage = findByPageBySqlId("findUserByNickName",map,page.getPageNo(),page.getPageSize());
		log.info(" ** 根据用户昵称搜索查询结果：{}",JSON.toJSONString(busiPage));
		// 3、BusiUser、UserInfoVO互转，UserInfoVO对外，BusiUser对内
		List<BusiUser> busiList = busiPage.getList();
		List<UserInfoVO> userInfoVOS = new ArrayList<>();
		List<String> ids = new ArrayList<>();
		String masterIds = "";
		busiList.forEach(busiUser -> {
			UserInfoVO userInfoVO = new UserInfoVO();
			BeanUtils.copyProperties(busiUser,userInfoVO);
			userInfoVOS.add(userInfoVO);
			ids.add(userInfoVO.getUserid());
		});
		if(ids != null && ids.size() > 0){
			for(String id : ids){
				masterIds = masterIds.concat(id+",");
			}
		}
		// 4、查询最近操作股票
		JSONObject result = stockApiClient.attentionUserByHexunIds(JSON.toJSONString(ids));
		if(result != null){
			log.info(" ** 查询用户最近操作股票返回数据：{}",result.toJSONString());
			userLateStock(result,userInfoVOS);
		}
		BaseResponse followListByHexunId = relationApiClient.followListByHexunId(userId);
		if("T".equals(followListByHexunId.getRespCode())){
			userLateRelation(userInfoVOS, followListByHexunId);
		}
		if (StringUtils.isNotEmpty(masterIds)) {
			BaseResponse masterRelation = relationApiClient.isMasterRelation(userId, masterIds.substring(0, masterIds.length()-1));
			if("T".equals(masterRelation.getRespCode())){
				userLateMaster(userInfoVOS, masterRelation);
			}
		}
		BeanUtils.copyProperties(busiPage,page,"list");
		page.setList(userInfoVOS);
		log.info(" ** 根据用户昵称搜索返回结果：{}",JSON.toJSONString(page));
		return page;
	}
	
	@SuppressWarnings("unchecked")
	private void userLateMaster(List<UserInfoVO> userInfoVOS, BaseResponse masterRelation) {
		List<Map<String, Object>> strList = (List<Map<String, Object>>)masterRelation.getResult();
		if (strList.size()>0) {
			for (int a = 0; a < strList.size(); a ++) {
				for(UserInfoVO userInfoVO : userInfoVOS){
					if(strList.get(a).get("userId").toString().equals(userInfoVO.getUserid())){
						userInfoVO.setIsMaster(strList.get(a).get("isMasterRelation").toString());
					}
				}
			}
		}
	}

	@SuppressWarnings("unchecked")
	private void userLateRelation(List<UserInfoVO> userInfoVOS, BaseResponse followListByHexunId) {
		List<String> hexunList = (List<String>) followListByHexunId.getResult();
		if(hexunList != null && hexunList.size() > 0){
			for(String id : hexunList){
				userInfoVOS.forEach(user ->{
					if(user.getUserid().equals(id)){
						user.setIsRelation(true);
					}
				});
			}
		}
	}
	
	/**
	 * 根据一串用户ID查询用户信息及最近操作股票
	 * @auther: zhoudong
	 * @date: 2018/6/1 17:52
	 */
	@Override
	public List<UserInfoVO> loadUserByUserIds(List<String> userIds, boolean b) {
		// List<BusiUser> users = busiUserMapper.findUsersByIds();
		List<UserInfoVO> users = new ArrayList<>();
		// 1、查询所有的用户信息
		userIds.forEach(userId -> users.add(loadUserInfo(userId)));

		if(b){
			// 2、查询最近操作股票信息
			JSONObject result = stockApiClient.attentionUserByHexunIds(JSON.toJSONString(userIds));
			if(result != null){
				log.info(" ** 查询用户最近操作股票返回数据：{}",result.toJSONString());
				userLateStock(result,users);
			}
		}

		return users;
	}
	/**
	 * 根据一串openid获取userid
	 * @auther: zhoudong
	 * @date: 2018/6/4 12:32
	 */
	@Override
	public List<Map<String, String>> decryptUserIds(String openIds) {
		List<Map<String,String>> list = new ArrayList<>();
		Map<String,String> map = null;
		String userId = null;
		if(StringUtils.isNotBlank(openIds) && openIds.contains(",")){
			String[] openIdArr = openIds.split(",");
			for (String id : openIdArr) {
				map = new HashMap<>();
				userId = AESEncryptUtils.base64decrypt(id);
				map.put(id,AESEncryptUtils.decrypt(userId,config.getOpenIdKey()));
				list.add(map);
			}
		}else if(StringUtils.isNotBlank(openIds)){
			map = new HashMap<>();
			userId = AESEncryptUtils.base64decrypt(openIds);
			map.put(openIds,AESEncryptUtils.decrypt(userId,config.getOpenIdKey()));
			list.add(map);
		}

		log.info(" decryptUserId openId:{} return:{}",openIds,JSON.toJSONString(list));
		return list;
	}

	/**
	 * 用户最近操作股票
	 * @auther: zhoudong
	 * @date: 2018/5/31 14:37
	 */
	private void userLateStock(JSONObject jsonObject, List<UserInfoVO> userInfoVOS) {
		if("ok".equals(jsonObject.getString("resultKey"))){
			JSONArray jsonArray = jsonObject.getJSONObject("data").getJSONArray("attentionUsers");
			for(int i=0; i < jsonArray.size(); i++){
				int finalI = i;
				userInfoVOS.forEach(user ->{
					if(user.getUserid().equals(jsonArray.getJSONObject(finalI).getString("hexun_id"))){
						Map<String,Object> stockMap = stockMap = new HashMap<>();
						stockMap.put("late_stock",jsonArray.getJSONObject(finalI));
						user.setStock(stockMap);
					}
				});
			}
		}
	}

}
